package gestIT;

import java.util.Vector;

/**
 * Class that represent the event Emitter, all the event from the source must be enclosed inside an ExpEventArgs and must be delivered to the Emitter
 * 
 * @author nicola
 *
 */
public class Emitter {

	/** The gesture that will be feed by the emitter */
	protected TmpExp gesture;
	/** A vector containing all the leaf of the gesture-graph */
	protected Vector<SimpleTmpExp> leafs;
	/** A vector containing a flag for each element in leafs */
	protected Vector<Boolean> flags;
	
	/**
	 * Constructor that create a new empty emitter
	 */
	public Emitter(){
		gesture = null;
		leafs = new Vector<SimpleTmpExp>();
		flags = new Vector<Boolean>();
	}
	
	/**
	 * Method that set the Gesture Description and generate the leafs and the flags vector
	 * @param gest
	 */
	public void SetGestureDescription(TmpExp gest){
		leafs.clear();
		flags.clear();
		this.gesture = gest;
		CreateLeafList(gesture);
	}
	
	/**
	 * Execute one step of the gesture, starting from new event arguments.
	 * All the event from the device must be send to the emitter throug this method
	 * @param arg The new event params
	 */
	public void FeedDeviceEvent(ExpEventArgs arg){
		
		int i;
		SimpleTmpExp tmpleaf;
		Boolean tmpflag;
		
		
		for (i = 0; i < leafs.size(); i++){
			tmpleaf = leafs.get(i);
			if (tmpleaf.state == ExecState.Enabled)
				flags.set(i, new Boolean(true));
		}
		
		boolean executed = false;
		for (i = 0; i < leafs.size(); i++){
			tmpleaf = leafs.get(i);
			tmpflag = flags.get(i);
			
			if (tmpflag.booleanValue() && tmpleaf != null && tmpleaf.Accepts(arg)){
				tmpleaf.Consume(arg);
				executed = true;
			}
			flags.set(i, new Boolean(false));
		}
		
		if (!executed){
			for (i = 0; i < leafs.size(); i++){
				tmpleaf = leafs.get(i);
				
				if (tmpleaf.state != ExecState.Disabled){
					tmpleaf.Invalidate(arg);
				}
			}	
		}
		
	}
	
	/**
	 * Start the recognition of the gesture setting the gesture state to enabled
	 * @param token
	 */
	public void StartRecognition(Token token){
		if (gesture != null){
			gesture.SetExecState(ExecState.Disabled, token);
			gesture.SetExecState(ExecState.Enabled, token);
		}
	}
	
	/**
	 * Create the gesture leaf list from a gesture definition
	 * @param gest The gesture definition
	 */
	public void CreateLeafList(TmpExp gest){
		if (gest == null)
			return;
		else
			switch (gest.type) {
			case Simple:
				SimpleTmpExp smpl = (SimpleTmpExp)gest;
				leafs.add(smpl);
				flags.add(new Boolean(false));
				break;

			case Binary:
				BinaryTmpExp bnry = (BinaryTmpExp)gest;
				this.CreateLeafList(bnry.getLeftOperand());
				this.CreateLeafList(bnry.getRightOperand());
				break;
				
			case Complex:
				
				int i;
				ComplexTmpExp cplx = (ComplexTmpExp)gest;

				for (i = 0; i < cplx.operands.size(); i++)
					CreateLeafList(cplx.operands.get(i));
				
				break;
			}
	}
	
}
